home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
Utilities.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
15KB
|
455 lines
/*
* @(#)Utilities.java 1.17 98/04/09
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.text;
import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.text.*;
/**
* A collection of methods to deal with various text
* related activities.
*
* @author Timothy Prinzing
* @version 1.17 04/09/98
*/
public class Utilities {
/**
* Draws the given text, expanding any tabs that are contained
* using the given tab expansion technique. This particular
* implementation renders in a 1.1 style coordinate system
* where ints are used and 72dpi is assumed.
*
* @param s the source of the text
* @param x the X origin >= 0
* @param y the Y origin >= 0
* @param g the graphics context
* @param e how to expand the tabs. If this value is null,
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @returns the X location at the end of the rendered text
*/
public static final int drawTabbedText(Segment s, int x, int y, Graphics g,
TabExpander e, int startOffset) {
FontMetrics metrics = g.getFontMetrics();
int nextX = x;
char[] txt = s.array;
int flushLen = 0;
int flushIndex = s.offset;
int n = s.offset + s.count;
for (int i = s.offset; i < n; i++) {
if (txt[i] == '\t') {
if (flushLen > 0) {
g.drawChars(txt, flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX, startOffset + i - s.offset);
} else {
nextX += metrics.charWidth(' ');
}
x = nextX;
} else if ((txt[i] == '\n') || (txt[i] == '\r')) {
if (flushLen > 0) {
g.drawChars(txt, flushIndex, flushLen, x, y);
flushLen = 0;
}
flushIndex = i + 1;
x = nextX;
} else {
flushLen += 1;
nextX += metrics.charWidth(txt[i]);
}
}
if (flushLen > 0) {
g.drawChars(txt, flushIndex, flushLen, x, y);
}
return nextX;
}
/**
* Determines the width of the given segment of text taking tabs
* into consideration. This is implemented in a 1.1 style coordinate
* system where ints are used and 72dpi is assumed.
*
* @param s the source of the text
* @param metrics the font metrics to use for the calculation
* @param x the X origin >= 0
* @param e how to expand the tabs. If this value is null,
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @returns the width of the text
*/
public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, int x,
TabExpander e, int startOffset) {
int nextX = x;
char[] txt = s.array;
int n = s.offset + s.count;
for (int i = s.offset; i < n; i++) {
if (txt[i] == '\t') {
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX,
startOffset + i - s.offset);
} else {
nextX += metrics.charWidth(' ');
}
} else {
nextX += metrics.charWidth(txt[i]);
}
}
return nextX - x;
}
/**
* Determines the relative offset into the given text that
* best represents the given span in the view coordinate
* system. This is implemented in a 1.1 style coordinate
* system where ints are used and 72dpi is assumed.
*
* @param s the source of the text
* @param metrics the font metrics to use for the calculation
* @param x0 the starting view location representing the start
* of the given text >= 0.
* @param x the target view location to translate to an
* offset into the text >= 0.
* @param e how to expand the tabs. If this value is null,
* tabs will be expanded as a space character.
* @param startOffset starting offset of the text in the document >= 0
* @returns the offset into the text >= 0
*/
public static final int getTabbedTextOffset(Segment s, FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset) {
int currX = x0;
int nextX = currX;
char[] txt = s.array;
int n = s.offset + s.count;
for (int i = s.offset; i < n; i++) {
if (txt[i] == '\t') {
if (e != null) {
nextX = (int) e.nextTabStop((float) nextX,
startOffset + i - s.offset);
} else {
nextX += metrics.charWidth(' ');
}
} else {
nextX += metrics.charWidth(txt[i]);
}
if ((x >= currX) && (x < nextX)) {
// found the hit position... return the appropriate side
if ((x - currX) < (nextX - x)) {
return i - s.offset;
} else {
return i + 1 - s.offset;
}
}
currX = nextX;
}
// didn't find, return end offset
return s.count;
}
/**
* Determine where to break the given text to fit
* within the the given span. This trys to find a
* whitespace boundry.
* @param s the source of the text
* @param metrics the font metrics to use for the calculation
* @param x0 the starting view location representing the start
* of the given text.
* @param x the target view location to translate to an
* offset into the text.
* @param e how to expand the tabs. If this value is null,
* tabs will be expanded as a space character.
* @param startOffset starting offset in the document of the text
* @returns the offset into the given text.
*/
public static final int getBreakLocation(Segment s, FontMetrics metrics,
int x0, int x, TabExpander e,
int startOffset) {
int index = Utilities.getTabbedTextOffset(s, metrics, x0, x, e, startOffset);
for (int i = s.offset + Math.min(index, s.count - 1);
i >= s.offset; i--) {
char ch = s.array[i];
if (Character.isWhitespace(ch)) {
// found whitespace, break here
index = i - s.offset + 1;
break;
}
}
return index;
}
/**
* Determines the starting row model position of the row that contains
* the specified model position. Assumes the row(s) are currently
* displayed in a view.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @return the position >= 0
* @exception BadLocationException if the offset is out of range
*/
public static final int getRowStart(JTextComponent c, int offs) throws BadLocationException {
Rectangle r = c.modelToView(offs);
int lastOffs = offs;
int y = r.y;
while ((r != null) && (y == r.y)) {
offs = lastOffs;
lastOffs -= 1;
r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
}
return offs;
}
/**
* Determines the ending row model position of the row that contains
* the specified model position. Assumes the row(s) are currently
* displayed in a view.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @return the position >= 0
* @exception BadLocationException if the offset is out of range
*/
public static final int getRowEnd(JTextComponent c, int offs) throws BadLocationException {
Rectangle r = c.modelToView(offs);
int n = c.getDocument().getLength();
int lastOffs = offs;
int y = r.y;
while ((r != null) && (y == r.y)) {
offs = lastOffs;
lastOffs += 1;
r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
}
return offs;
}
/**
* Determines the position in the model that is closest to the given
* view location in the row above.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @param x the X coordinate >= 0
* @return the model position >= 0
* @exception BadLocationException if the offset is out of range
*/
public static final int getPositionAbove(JTextComponent c, int offs, int x) throws BadLocationException {
int lastOffs = getRowStart(c, offs) - 1;
int bestSpan = Short.MAX_VALUE;
int y = 0;
Rectangle r = null;
if (lastOffs >= 0) {
r = c.modelToView(lastOffs);
y = r.y;
}
while ((r != null) && (y == r.y)) {
int span = Math.abs(r.x - x);
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs -= 1;
r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
}
return offs;
}
/**
* Determines the position in the model that is closest to the given
* view location in the row below.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @param x the X coordinate >= 0
* @return the model position >= 0
* @exception BadLocationException if the offset is out of range
*/
public static final int getPositionBelow(JTextComponent c, int offs, int x) throws BadLocationException {
int lastOffs = getRowEnd(c, offs) + 1;
int bestSpan = Short.MAX_VALUE;
int n = c.getDocument().getLength();
int y = 0;
Rectangle r = null;
if (lastOffs <= n) {
r = c.modelToView(lastOffs);
y = r.y;
}
while ((r != null) && (y == r.y)) {
int span = Math.abs(x - r.x);
if (span < bestSpan) {
offs = lastOffs;
bestSpan = span;
}
lastOffs += 1;
r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
}
return offs;
}
/**
* Determines the start of a word for the given model location.
* Uses BreakIterator.getWordInstance() to actually get the words.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @returns the location in the model of the word start >= 0.
* @exception BadLocationException if the offset is out of range
*/
public static final int getWordStart(JTextComponent c, int offs) throws BadLocationException {
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
String s = doc.getText(lineStart, lineEnd - lineStart);
if(s != null && s.length() > 0) {
BreakIterator words = BreakIterator.getWordInstance();
words.setText(s);
int wordPosition = offs - lineStart;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
words.following(wordPosition);
offs = lineStart + words.previous();
}
return offs;
}
/**
* Determines the end of a word for the given location.
* Uses BreakIterator.getWordInstance() to actually get the words.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @returns the location in the model of the word end >= 0.
* @exception BadLocationException if the offset is out of range
*/
public static final int getWordEnd(JTextComponent c, int offs) throws BadLocationException {
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
String s = doc.getText(lineStart, lineEnd - lineStart);
if(s != null && s.length() > 0) {
BreakIterator words = BreakIterator.getWordInstance();
words.setText(s);
int wordPosition = offs - lineStart;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
offs = lineStart + words.following(wordPosition);
}
return offs;
}
/**
* Determines the start of the next word for the given location.
* Uses BreakIterator.getWordInstance() to actually get the words.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @returns the location in the model of the word start >= 0.
* @exception BadLocationException if the offset is out of range
*/
public static final int getNextWord(JTextComponent c, int offs) throws BadLocationException {
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
String s = doc.getText(lineStart, lineEnd - lineStart);
if(s != null && s.length() > 0) {
BreakIterator words = BreakIterator.getWordInstance();
words.setText(s);
int wordPosition = offs - lineStart;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
words.following(wordPosition);
offs = lineStart + words.next();
}
return offs;
}
/**
* Determine the start of the next word for the given location.
* Uses BreakIterator.getWordInstance() to actually get the words.
*
* @param c the editor
* @param offs the offset in the document >= 0
* @returns the location in the model of the word start >= 0.
* @exception BadLocationException if the offset is out of range
*/
public static final int getPreviousWord(JTextComponent c, int offs) throws BadLocationException {
Document doc = c.getDocument();
Element line = getParagraphElement(c, offs);
int lineStart = line.getStartOffset();
int lineEnd = Math.min(line.getEndOffset(), doc.getLength());
String s = doc.getText(lineStart, lineEnd - lineStart);
if(s != null && s.length() > 0) {
BreakIterator words = BreakIterator.getWordInstance();
words.setText(s);
int wordPosition = offs - lineStart;
if(wordPosition >= words.last()) {
wordPosition = words.last() - 1;
}
words.following(wordPosition);
if (offs == (lineStart + words.previous())) {
words.previous();
int o = words.previous();
if (o == BreakIterator.DONE) {
offs = lineStart;
} else {
offs = lineStart + o;
}
}
}
return offs;
}
/**
* Determines the element to use for a paragraph/line.
*
* @param c the editor
* @param offs the starting offset in the document >= 0
* @return the element
*/
public static final Element getParagraphElement(JTextComponent c, int offs) {
Document doc = c.getDocument();
if (doc instanceof StyledDocument) {
return ((StyledDocument)doc).getParagraphElement(offs);
}
Element map = doc.getDefaultRootElement();
int index = map.getElementIndex(offs);
Element paragraph = map.getElement(index);
return paragraph;
}
}